class Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack
  ) {
    this.id = id;
    this.type = type;
    this.x = x;
    this.y = y;
    this.r = r;
    this.hp = hp;
    this.futureHP = this.hp;
    this.material = material;
    this.speed = speed;
    this.damage = damage;
    this.shape = shape;
    this.color = color;
    this.invincible = invincible;
    this.invincibleForGuard = invincibleForGuard;
    this.markDeath = markDeath;
    this.moveType = moveType;
    this.resistKnockBack = resistKnockBack;
  }

  draw(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
  }
}

class BubbleEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    attackInterval,
    bulletDamage
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.attackInterval = attackInterval;
    this.bulletDamage = bulletDamage;
  }

  draw(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.beginPath();
    ctx.arc(this.x, this.y - r / 2, r / 2, 0, 2 * Math.PI);
    ctx.fillStyle = "#ffffff";
    ctx.fill();
  }
}

class MachineEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    attackInterval,
    bulletDamage
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.attackInterval = attackInterval;
    this.bulletDamage = bulletDamage;
  }

  draw(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(this.x, this.y - r / 1.3, r / 4.5, r / 3.5, 0, 0, Math.PI * 2);
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x - r * 0.64,
      this.y - r / 2.5,
      r / 4.5,
      r / 3.5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x + r * 0.64,
      this.y - r / 2.5,
      r / 4.5,
      r / 3.5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
  }
}

class ChargeEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    attackInterval,
    bulletDamage,
    bulletNumber,
    attackRestInterval
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.attackInterval = attackInterval;
    this.bulletDamage = bulletDamage;
    this.bulletNumber = bulletNumber;
    this.attackRestInterval = attackRestInterval;
  }

  draw(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
    var arr = this.createRegTriArr(this.x, this.y, r / 4 - dpr * 0.5);
    var arrLeft = this.createRegTriArr(arr[0].x, arr[0].y, r / 1.5);
    var arrRight = this.createRegTriArr(arr[1].x, arr[1].y, r / 1.5);
    var arrTop = this.createRegTriArr(arr[2].x, arr[2].y, r / 1.5);
    ctx.beginPath();
    ctx.moveTo(arrTop[0].x, arrTop[0].y);
    ctx.lineTo(arrLeft[2].x, arrLeft[2].y);
    ctx.arcTo(arrLeft[0].x, arrLeft[0].y, arrLeft[1].x, arrLeft[1].y, dpr * 3);
    ctx.lineTo(arrRight[0].x, arrRight[0].y);
    ctx.arcTo(
      arrRight[1].x,
      arrRight[1].y,
      arrRight[2].x,
      arrRight[2].y,
      dpr * 3
    );
    ctx.lineTo(arrTop[1].x, arrTop[1].y);
    ctx.arcTo(arrTop[2].x, arrTop[2].y, arrTop[0].x, arrTop[0].y, dpr * 3);
    ctx.closePath();
    ctx.fillStyle = "#ffffff";
    ctx.fill();
  }

  createRegTriArr(x, y, r) {
    var arr = new Array();

    for (var i = 0; i < 3; i++) {
      var theta = ((Math.PI * 2) / 3) * i + Math.PI / 6;
      var pt = this.createPt(r * Math.cos(theta) + x, r * Math.sin(theta) + y);
      arr.push(pt);
    }
    return arr;
  }

  createPt(x, y) {
    var retval = {};
    retval.x = x;
    retval.y = y;
    return retval;
  }

  //   draw(ctx) {
  //     var templateX = myX - this.x;
  //     var templateY = myY - this.y;
  //     var radians = Math.atan2(templateY, templateX);
  //     var a = 2 * dpr;
  //     var b = 5 * dpr;

  //     var headscarfRadians = (-radians - Math.PI / 2 + 2 * Math.PI) % (2 * Math.PI);

  //     var subX = Math.cos(radians)* dpr;
  //     var subY = -Math.sin(radians) * dpr;

  //     //   绘制圆形头部
  //     ctx.beginPath();
  //     ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
  //     ctx.fillStyle = "black";
  //     ctx.fill();

  //     ctx.beginPath();
  //     ctx.rect(this.x - this.r / 2, this.y - this.r / 5, this.r, (2 * this.r) / 5); // 参数同fillRect
  //     ctx.fillStyle = "#f4ea2a";
  //     ctx.fill();

  //     ctx.beginPath();
  //     ctx.arc(this.x - this.r / 2, this.y, this.r / 5, 0, 2 * Math.PI);
  //     ctx.fillStyle = "#f4ea2a";
  //     ctx.fill();

  //     ctx.beginPath();
  //     ctx.arc(this.x + this.r / 2, this.y, this.r / 5, 0, 2 * Math.PI);
  //     ctx.fillStyle = "#f4ea2a";
  //     ctx.fill();

  //     ctx.beginPath();
  //     ctx.arc(this.x + this.r / 3 + subX, this.y - this.r / 10 - subY, this.r / 5, 0, Math.PI * 2);
  //     ctx.fillStyle = "black";
  //     ctx.fill();

  //     ctx.beginPath();
  //     ctx.arc(this.x - this.r / 3 + subX, this.y - this.r / 10 - subY, this.r / 5, 0, Math.PI * 2);
  //     ctx.fillStyle = "black";
  //     ctx.fill();
  //   }
}

class TankEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    sprintRadians,
    sprintInterval,
    sprintDuration
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.sprintRadians = sprintRadians;
    this.sprintInterval = sprintInterval;
    this.sprintDuration = sprintDuration;
  }

  draw(ctx) {
    //准备冲刺时绘制方向箭头
    if (this.sprintDuration > 100) {
      ctx.globalAlpha = 0.7;
      var templateX = myX - this.x;
      var templateY = myY - this.y;
      // 计算角度
      var enemyAngleInRadians = Math.atan2(templateY, templateX);

      var enemyVelocityX = Math.cos(enemyAngleInRadians) * dpr * 30;
      var enemyVelocityY = Math.sin(enemyAngleInRadians) * dpr * 30;

      ctx.save();

      ctx.translate(this.x + enemyVelocityX, this.y + enemyVelocityY);
      ctx.rotate(enemyAngleInRadians);
      ctx.translate(-this.x - enemyVelocityX, -this.y - enemyVelocityY);

      ctx.drawImage(
        sprintImage,
        this.x + enemyVelocityX - dpr * 10,
        this.y + enemyVelocityY - dpr * 10,
        dpr * 20,
        dpr * 20
      );

      ctx.restore();
      ctx.globalAlpha = 1.0;
    }

    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();

    var tankSubX = 0.8 * dpr * Math.cos(this.radians) * 3;
    var tankSubY = 0.8 * dpr * Math.sin(this.radians) * 2;
    ctx.beginPath();
    ctx.arc(
      this.x + tankSubX,
      this.y - r + tankSubY,
      this.r / 1.4,
      0,
      2 * Math.PI
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.arc(
      this.x + tankSubX,
      this.y - r + tankSubY,
      this.r / 1.5,
      0,
      2 * Math.PI
    );
    ctx.fillStyle = "#000000";
    ctx.fill();

    ctx.beginPath();
    ctx.ellipse(
      this.x + tankSubX * 1.5 - r / 2.5,
      this.y - r + 2 * tankSubY,
      r / 4.2,
      r / 3.4,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();

    ctx.beginPath();
    ctx.ellipse(
      this.x + tankSubX * 1.5 + r / 2.5,
      this.y - r + 2 * tankSubY,
      r / 4.2,
      r / 3.4,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();

    ctx.beginPath();
    ctx.arc(
      this.x - r / 1.5 + tankSubX * 2,
      this.y + r / 3,
      this.r / 3.5,
      0,
      2 * Math.PI
    );
    ctx.strokeStyle = "#000000";
    ctx.lineWidth = 2;
    ctx.stroke();
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.closePath();

    ctx.beginPath();
    ctx.arc(
      this.x + r / 1.5 + tankSubX * 2,
      this.y + r / 3,
      this.r / 3.5,
      0,
      2 * Math.PI
    );
    ctx.strokeStyle = "#000000";
    ctx.lineWidth = 2;
    ctx.stroke();
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.closePath();
  }
}

class BoomEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    boomInterval,
    boomDamage
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.boomInterval = boomInterval;
    this.boomDamage = boomDamage;
  }

  draw(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
    if (
      this.boomInterval < 50 &&
      calculateDistance({ x: myX, y: myY }, this) < Math.round(dpr * 180)
    ) {
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
      ctx.fillStyle = "#ff0000";
      ctx.fill();
    }
    ctx.beginPath();
    ctx.ellipse(
      this.x - r * 0.4,
      this.y - r / 1.4,
      r / 6,
      r / 5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x + r * 0.4,
      this.y - r / 1.4,
      r / 6,
      r / 5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(this.x, this.y - r / 7, r / 1.5, r / 3, 0, 0, Math.PI * 2);
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.strokeStyle = "black";
    ctx.lineWidth = dpr * 0.3;
    ctx.beginPath();
    ctx.moveTo(this.x - r / 1.5, this.y - r / 7);
    ctx.lineTo(this.x + r / 1.5, this.y - r / 7);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(this.x, this.y - r / 7 - r / 3);
    ctx.lineTo(this.x, this.y - r / 7 + r / 3);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(this.x - r / 3, this.y - r / 7 - r / 3);
    ctx.lineTo(this.x - r / 3, this.y - r / 7 + r / 3);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(this.x + r / 3, this.y - r / 7 - r / 3);
    ctx.lineTo(this.x + r / 3, this.y - r / 7 + r / 3);
    ctx.stroke();
  }
}

class TrapEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    bulletDamage
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.bulletDamage = bulletDamage;
  }

  draw(ctx) {
    var trapSubX = 0.8 * dpr * Math.cos(this.radians) * 2;
    var trapSubY = 0.8 * dpr * Math.sin(this.radians) * 1.5;

    ctx.beginPath();
    ctx.arc(this.x, this.y - this.r / 2, this.r / 1.6, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x - this.r / 4 + trapSubX,
      this.y - this.r / 2 + trapSubY,
      this.r / 8,
      this.r / 6,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x + this.r / 4 + trapSubX,
      this.y - this.r / 2 + trapSubY,
      this.r / 7,
      this.r / 5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();

    ctx.beginPath();
    ctx.arc(
      this.x - this.r / 2,
      this.y + this.r / 3,
      this.r / 1.6,
      0,
      2 * Math.PI
    );
    ctx.fillStyle = this.color;
    ctx.fill();

    ctx.beginPath();
    ctx.ellipse(
      this.x - this.r / 1.8 - this.r / 4 + trapSubX,
      this.y + this.r / 3 + trapSubY,
      this.r / 8,
      this.r / 6,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x - this.r / 1.8 + this.r / 4 + trapSubX,
      this.y + this.r / 2.5 + trapSubY,
      this.r / 7,
      this.r / 5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();

    ctx.beginPath();
    ctx.arc(
      this.x + this.r / 2,
      this.y + this.r / 3,
      this.r / 1.6,
      0,
      2 * Math.PI
    );
    ctx.fillStyle = this.color;
    ctx.fill();

    ctx.beginPath();
    ctx.ellipse(
      this.x + this.r / 1.8 - this.r / 4 + trapSubX,
      this.y + this.r / 2.5 + trapSubY,
      this.r / 7,
      this.r / 5,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.beginPath();
    ctx.ellipse(
      this.x + this.r / 1.8 + this.r / 4 + trapSubX,
      this.y + this.r / 3 + trapSubY,
      this.r / 8,
      this.r / 6,
      0,
      0,
      Math.PI * 2
    );
    ctx.fillStyle = "#ffffff";
    ctx.fill();
  }
}

class MissileEnemy extends Enemy {
  constructor(
    id,
    type,
    x,
    y,
    r,
    hp,
    material,
    speed,
    damage,
    shape,
    color,
    invincible,
    invincibleForGuard,
    markDeath,
    moveType,
    resistKnockBack,
    attackInterval,
    bulletDamage
  ) {
    super(
      id,
      type,
      x,
      y,
      r,
      hp,
      material,
      speed,
      damage,
      shape,
      color,
      invincible,
      invincibleForGuard,
      markDeath,
      moveType,
      resistKnockBack
    );
    this.attackInterval = attackInterval;
    this.bulletDamage = bulletDamage;
  }

  draw(ctx) {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.beginPath();
    ctx.arc(this.x, this.y, r / 1.8, 0, 2 * Math.PI);
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.strokeStyle = "black";
    ctx.lineWidth = dpr * 0.4;
    ctx.beginPath();
    ctx.moveTo(this.x, this.y - r / 1.8);
    ctx.lineTo(this.x, this.y + r / 1.8);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(this.x - r / 1.8, this.y);
    ctx.lineTo(this.x + r / 1.8, this.y);
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(this.x, this.y, r / 3.5, 0, 2 * Math.PI);
    ctx.stroke();
  }
}

class EnemyBullet {
  constructor(type, x, y, r, radians, distance, damage, duration) {
    this.type = type;
    this.x = x;
    this.y = y;
    this.r = r;
    this.radians = radians;
    this.distance = distance;
    this.damage = damage;
    this.duration = duration;
  }

  drawRound(ctx) {
    ctx.save();
    ctx.shadowBlur = r / 4;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;
    ctx.shadowColor = "#444444";
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = "#444444";
    ctx.fill();
    ctx.closePath();
    ctx.shadowBlur = 0;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r * 0.9, 0, 2 * Math.PI);
    ctx.fillStyle = "#ff0000";
    ctx.fill();
    ctx.closePath();
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r * 0.45, 0, 2 * Math.PI);
    ctx.fillStyle = "#ffffff";
    ctx.fill();
    ctx.closePath();
    ctx.restore();
  }

  drawTriangle(ctx, dpr) {
    ctx.save();
    ctx.shadowBlur = 0;
    ctx.translate(this.x, this.y);
    ctx.rotate(this.radians - Math.PI / 6);
    ctx.translate(-this.x, -this.y);
    var arr = this.createRegTriArr(this.x, this.y, (dpr * 10) / 4 - dpr * 0.5);
    var arrLeft = this.createRegTriArr(arr[0].x, arr[0].y, (dpr * 10) / 1.3);
    var arrRight = this.createRegTriArr(arr[1].x, arr[1].y, (dpr * 10) / 1.3);
    var arrTop = this.createRegTriArr(arr[2].x, arr[2].y, (dpr * 10) / 1.3);
    ctx.beginPath();
    ctx.moveTo(arrTop[0].x, arrTop[0].y);
    ctx.lineTo(arrLeft[2].x, arrLeft[2].y);
    ctx.arcTo(arrLeft[0].x, arrLeft[0].y, arrLeft[1].x, arrLeft[1].y, dpr * 3);
    ctx.lineTo(arrRight[0].x, arrRight[0].y);
    ctx.arcTo(
      arrRight[1].x,
      arrRight[1].y,
      arrRight[2].x,
      arrRight[2].y,
      dpr * 3
    );
    ctx.lineTo(arrTop[1].x, arrTop[1].y);
    ctx.arcTo(arrTop[2].x, arrTop[2].y, arrTop[0].x, arrTop[0].y, dpr * 3);
    ctx.closePath();
    ctx.fillStyle = "#ff0000";
    ctx.fill();
    ctx.restore();
  }

  drawMissile(ctx, dpr) {
    ctx.save();
    ctx.translate(this.x, this.y);
    ctx.rotate(this.radians + Math.PI / 2);
    ctx.translate(-this.x, -this.y);
    ctx.drawImage(
      missileImage,
      this.x - dpr * 10,
      this.y - dpr * 10,
      dpr * 20,
      dpr * 20
    );
    ctx.restore();

    var templateX = myX - this.x;
    var templateY = myY - this.y;
    // 计算子弹到玩家的角度（使用快速近似 atan2 或缓存结果）
    var targetAngle = Math.atan2(templateY, templateX);

    // 计算角度差并规范化到 [-PI, PI]
    var angleDiff = targetAngle - this.radians;
    angleDiff -= angleDiff > Math.PI ? 2 * Math.PI : 0;
    angleDiff += angleDiff < -Math.PI ? 2 * Math.PI : 0;

    // 限制角度变化不超过 Math.PI/400
    var maxTurn = Math.PI / 400;
    angleDiff = Math.max(-maxTurn, Math.min(maxTurn, angleDiff));

    // 更新子弹角度（避免循环规范化，使用模运算）
    this.radians += angleDiff;
    this.radians =
      (((this.radians % (2 * Math.PI)) + 3 * Math.PI) % (2 * Math.PI)) -
      Math.PI;

    //新建甩尾
    var subX = -dpr * Math.cos(this.radians) * 10;
    var subY = -dpr * Math.sin(this.radians) * 10;
    driftList.push(
      new Drift(
        this.x + (Math.random() * r) / 6 - r / 12 + subX,
        this.y + (Math.random() * r) / 6 - r / 12 + subY,
        (Math.random() * r) / 7 + r / 10,
        30,
        0.96,
        "#ff0000"
      )
    );
  }

  createRegTriArr(x, y, r) {
    var arr = new Array();

    for (var i = 0; i < 3; i++) {
      var theta = ((Math.PI * 2) / 3) * i + Math.PI / 6;
      var pt = this.createPt(r * Math.cos(theta) + x, r * Math.sin(theta) + y);
      arr.push(pt);
    }
    return arr;
  }

  createPt(x, y) {
    var retval = {};
    retval.x = x;
    retval.y = y;
    return retval;
  }
}

class Gun {
  constructor(
    baseX,
    baseY,
    damage,
    distance,
    baseInterval,
    currentInterval,
    range,
    position
  ) {
    this.baseX = baseX;
    this.baseY = baseY;
    this.damage = damage;
    this.distance = distance;
    this.baseInterval = baseInterval;
    this.currentInterval = currentInterval;
    this.range = range;
    this.position = position;
  }
}

class Bullet {
  constructor(
    x,
    y,
    baseX,
    baseY,
    damage,
    fireX,
    fireY,
    radians,
    distance,
    range,
    currentPath,
    position,
    bounce,
    pierce,
    attackList
  ) {
    this.x = x;
    this.y = y;
    this.baseX = baseX;
    this.baseY = baseY;
    this.damage = damage;
    this.fireX = fireX;
    this.fireY = fireY;
    this.radians = radians;
    this.distance = distance;
    this.range = range;
    this.currentPath = currentPath;
    this.position = position;
    this.bounce = bounce;
    this.pierce = pierce;
    this.attackList = attackList;
  }
}

class Spark {
  constructor(x, y, radians, r, range, duration, color) {
    this.x = x;
    this.y = y;
    this.radians = radians;
    this.r = r;
    this.range = range;
    this.duration = duration;
    this.color = color;
  }
}

class Drift {
  constructor(x, y, r, duration, decay, color) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.duration = duration;
    this.decay = decay;
    this.color = color;
  }
}

class BoomSpark {
  constructor(x, y, r, duration, color) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.duration = duration;
    this.color = color;
  }
}

class Explosion {
  constructor(x, y, duration, growthSpeed) {
    this.x = x;
    this.y = y;
    this.radius = 0; // 初始半径
    this.color = "red";
    this.alpha = 1; // 初始透明度
    this.growthSpeed = growthSpeed; // 扩张速度
    this.fadeSpeed = 0.03; // 消失速度
    this.duration = duration;
  }

  update() {
    this.radius += this.growthSpeed;
    this.alpha -= this.fadeSpeed;

    if (this.duration < 5) {
      this.growthSpeed *= 0.5;
    }

    this.duration--;
  }

  draw(ctx) {
    ctx.save();
    ctx.globalAlpha = this.alpha;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();

    // 添加内圈使爆炸更有层次感
    if (this.alpha > 0.5) {
      ctx.globalAlpha = this.alpha * 0.7;
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.radius * 0.7, 0, Math.PI * 2);
      ctx.fillStyle = "white";
      ctx.fill();
    }
    ctx.restore();
  }
}

class Deduction {
  constructor(x, y, n, color, size, duration) {
    this.x = x;
    this.y = y;
    this.n = n;
    this.color = color;
    this.size = size;
    this.duration = duration;
  }
}

class Corpse {
  constructor(x, y, r, distance, radians, delay) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.distance = distance;
    this.radians = radians;
    this.delay = delay;
  }
}

class Food {
  constructor(x, y, w, h, radius, radians, color, number) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.radius = radius;
    this.radians = radians;
    this.color = color;
    this.number = number;
  }

  draw(ctx) {
    ctx.save();
    // ctx.shadowBlur = this.w / 3;
    // ctx.shadowOffsetX = 0;
    // ctx.shadowOffsetY = 0;
    // ctx.shadowColor = this.color;

    ctx.translate(this.x, this.y);
    // 再旋转画布
    ctx.rotate(this.radians);
    ctx.translate(-this.x, -this.y);
    // 开始路径
    ctx.beginPath();
    ctx.moveTo(this.x + this.radius, this.y); // 移动到左上角
    ctx.lineTo(this.x + this.w - this.radius, this.y); // 绘制左上角到右上角的直线
    ctx.quadraticCurveTo(
      this.x + this.w,
      this.y,
      this.x + this.w,
      this.y + this.radius
    ); // 绘制右上角的圆角
    ctx.lineTo(this.x + this.w, this.y + this.h - this.radius); // 绘制右上角到右下角的直线
    ctx.quadraticCurveTo(
      this.x + this.w,
      this.y + this.h,
      this.x + this.w - this.radius,
      this.y + this.h
    ); // 绘制右下角的圆角
    ctx.lineTo(this.x + this.radius, this.y + this.h); // 绘制右下角到左下角的直线
    ctx.quadraticCurveTo(
      this.x,
      this.y + this.h,
      this.x,
      this.y + this.h - this.radius
    ); // 绘制左下角的圆角
    ctx.lineTo(this.x, this.y + this.radius); // 绘制左下角到左上角的直线
    ctx.quadraticCurveTo(this.x, this.y, this.x + this.radius, this.y); // 绘制左上角的圆角
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.closePath();
    ctx.restore();
  }
}

class Plant {
  constructor(id, x, y, hp) {
    this.id = id;
    this.x = x;
    this.y = y;
    this.hp = hp;
  }
}

class Guard {
  constructor(x, y, R, r, speed, radians, color, damage) {
    this.x = x;
    this.y = y;
    this.R = R;
    this.r = r;
    this.speed = speed;
    this.radians = radians;
    this.color = color;
    this.damage = damage;
  }
}

class Buff {
  constructor(x, y, r, color, type, duration) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.color = color;
    this.type = type;
    this.duration = duration;
  }
}

class Rok {
  constructor(
    x,
    y,
    centerX,
    centerY,
    headX,
    headY,
    l,
    radians,
    range,
    actionRange,
    duration,
    interval,
    direction,
    position
  ) {
    this.x = x;
    this.y = y;
    this.centerX = centerX;
    this.centerY = centerY;
    this.headX = headX;
    this.headY = headY;
    this.l = l;
    this.radians = radians;
    this.range = range;
    this.actionRange = actionRange;
    this.duration = duration;
    this.interval = interval;
    this.direction = direction;
    this.position = position;
  }
}

//突刺备案
// function Rok(x, y, centerX, centerY, headX, headY, footX, footY, l, radians, actionRadians, range, actionRange, interval) {
//     this.x = x
//     this.y = y
//     this.centerX = centerX
//     this.centerY = centerY
//     this.headX = headX
//     this.headY = headY
//     this.footX = footX
//     this.footY = footY
//     this.l = l
//     this.radians = radians
//     this.actionRadians = actionRadians
//     this.range = range
//     this.actionRange = actionRange
//     this.interval = interval
// }
